/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ZorNavFrame.java
 *
 * Created on 23.12.2011, 14:46:11
 */
package com.transas.zornav.ui;

import com.transas.navmath.Pos2D;
import com.transas.navmath.Pos3D;
import com.transas.zornav.businesslogic.Calculator;
import com.transas.zornav.businesslogic.Config;
import com.transas.zornav.data.DataSource;
import com.transas.zornav.data.DegMinSecFormatter;
import com.transas.zornav.data.SimpleFormatter;
import com.transas.zornav.data.TimeFormatter;
import com.transas.zornav.file.*;
import java.io.*;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author amalikov
 */
public class ZorNavFrame extends javax.swing.JFrame {
	private final static Logger LOG = Logger.getLogger(ZorNavFrame.class.getName());

	/** Creates new form ZorNavFrame */
	public ZorNavFrame() {
		ds = null;
		calc = new Calculator();
		lastDir = null;
		filename = null;
		createDataSource();
		initComponents();
		updateTitle(null);
		updateUIFromConfig();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        tableScrollPane = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
        ias = new javax.swing.JTextField();
        javax.swing.JLabel jLabel2 = new javax.swing.JLabel();
        javax.swing.JLabel jLabel7 = new javax.swing.JLabel();
        windDir = new javax.swing.JTextField();
        javax.swing.JLabel jLabel8 = new javax.swing.JLabel();
        windSpeed = new javax.swing.JTextField();
        javax.swing.JLabel jLabel9 = new javax.swing.JLabel();
        javax.swing.JLabel jLabel3 = new javax.swing.JLabel();
        fuelTotal = new javax.swing.JTextField();
        javax.swing.JLabel jLabel4 = new javax.swing.JLabel();
        javax.swing.JLabel jLabel5 = new javax.swing.JLabel();
        fuelRate = new javax.swing.JTextField();
        javax.swing.JLabel jLabel6 = new javax.swing.JLabel();
        javax.swing.JLabel jLabel10 = new javax.swing.JLabel();
        recalcButton = new javax.swing.JButton();
        departure = new javax.swing.JFormattedTextField();
        NowBtn = new javax.swing.JButton();
        decimalDegrees = new javax.swing.JCheckBox();
        menu = new javax.swing.JMenuBar();
        menuFile = new javax.swing.JMenu();
        menuFileOpen = new javax.swing.JMenuItem();
        menuFileAppend = new javax.swing.JMenuItem();
        menuFileSave = new javax.swing.JMenuItem();
        menuFileExit = new javax.swing.JMenuItem();
        menuTools = new javax.swing.JMenu();
        menuToolsPattern = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("ZorNav");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(800, 600));
        setName("ZorNavFrame"); // NOI18N

        table.setModel(new javax.swing.table.DefaultTableModel());
        table.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        tableScrollPane.setViewportView(table);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Parameters"));

        jLabel1.setText("IAS:");

        jLabel2.setText("km/h");

        jLabel7.setText("Wind:");

        jLabel8.setText("° / ");

        jLabel9.setText("m/s");

        jLabel3.setText("Total fuel:");

        jLabel4.setText("liters");

        jLabel5.setText("Fuel rate:");

        jLabel6.setText("liters/h");

        jLabel10.setText("Departure:");

        recalcButton.setText("Recalc");
        recalcButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                recalcButtonActionPerformed(evt);
            }
        });

        try {
            departure.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("##:##:##")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }

        NowBtn.setText("Now");
        NowBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                NowBtnActionPerformed(evt);
            }
        });

        decimalDegrees.setText("Decimal degrees");
        decimalDegrees.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                decimalDegreesActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addGap(14, 14, 14)
                                .addComponent(fuelTotal, javax.swing.GroupLayout.PREFERRED_SIZE, 59, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel1)
                                .addGap(42, 42, 42)
                                .addComponent(ias, javax.swing.GroupLayout.PREFERRED_SIZE, 59, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel4)
                            .addComponent(jLabel2))
                        .addGap(18, 18, 18)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel7)
                            .addComponent(jLabel5))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(fuelRate)
                            .addComponent(windDir, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel8)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(windSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel9))
                            .addComponent(jLabel6)))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel10)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(departure, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(NowBtn)
                        .addGap(18, 18, 18)
                        .addComponent(decimalDegrees)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(recalcButton)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(ias, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(windDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(jLabel7)
                    .addComponent(jLabel8)
                    .addComponent(windSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(fuelTotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(jLabel5)
                    .addComponent(fuelRate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel10)
                    .addComponent(recalcButton)
                    .addComponent(departure, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(NowBtn)
                    .addComponent(decimalDegrees))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        menuFile.setText("File");

        menuFileOpen.setText("Open");
        menuFileOpen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuFileOpenActionPerformed(evt);
            }
        });
        menuFile.add(menuFileOpen);

        menuFileAppend.setText("Append");
        menuFileAppend.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuFileAppendActionPerformed(evt);
            }
        });
        menuFile.add(menuFileAppend);

        menuFileSave.setText("Save as");
        menuFileSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuFileSaveActionPerformed(evt);
            }
        });
        menuFile.add(menuFileSave);

        menuFileExit.setText("Exit");
        menuFileExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuFileExitActionPerformed(evt);
            }
        });
        menuFile.add(menuFileExit);

        menu.add(menuFile);

        menuTools.setText("Tools");

        menuToolsPattern.setText("Pattern");
        menuToolsPattern.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuToolsPatternActionPerformed(evt);
            }
        });
        menuTools.add(menuToolsPattern);

        menu.add(menuTools);

        setJMenuBar(menu);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 751, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void menuFileExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuFileExitActionPerformed
		dispose();
	}//GEN-LAST:event_menuFileExitActionPerformed

	private void menuFileOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuFileOpenActionPerformed
		doOpenAppend(false);
	}//GEN-LAST:event_menuFileOpenActionPerformed

	private void recalcButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recalcButtonActionPerformed
		updateConfigFromUI();
		if (ds != null) {
			recalcDataSource();
			updateTable();
		}
	}//GEN-LAST:event_recalcButtonActionPerformed

	private void menuFileSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuFileSaveActionPerformed
		final JFileChooser fc = new JFileChooser((lastDir != null) ? lastDir : getHomeDir());
		fc.setAcceptAllFileFilterUsed(false);
		FileNameExtensionFilter defaultFilter = new FileNameExtensionFilter("Text log (*.txt)", "txt");
		fc.addChoosableFileFilter(defaultFilter);
		fc.addChoosableFileFilter(new FileNameExtensionFilter("GCS flight plan (*.task)", "task"));
		fc.addChoosableFileFilter(new FileNameExtensionFilter("GoogleEarth KML (*.kml)", "kml"));
		fc.addChoosableFileFilter(new FileNameExtensionFilter("MissionPlanner (*.txt)", "txt"));
		fc.setFileFilter(defaultFilter);
		
		if (filename != null)
			fc.setSelectedFile(new File(filename));

		if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
			String desc = ((FileNameExtensionFilter)fc.getFileFilter()).getDescription();
			String ext = ((FileNameExtensionFilter)fc.getFileFilter()).getExtensions()[0];
			String path = fc.getSelectedFile().getPath();
			if (!path.endsWith("." + ext))
				path += "." + ext;
			
			DataSourceWriter dsWriter;
			if (desc.startsWith("Text"))
				dsWriter = new TextDataSourceWriter();
			else if (desc.startsWith("GCS"))
				dsWriter = new TaskDataSourceWriter();
			else if (desc.startsWith("Google"))
				dsWriter = new KmlDataSourceWriter();
			else if (desc.startsWith("Mission"))
				dsWriter = new MissionPlannerDataSourceWriter();
			else
				return;
			
			doSave(path, dsWriter);
		}		
	}//GEN-LAST:event_menuFileSaveActionPerformed

	private void NowBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_NowBtnActionPerformed
		DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
		Date date = new Date();
		departure.setText(dateFormat.format(date));
	}//GEN-LAST:event_NowBtnActionPerformed

	private void decimalDegreesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_decimalDegreesActionPerformed
		recalcButtonActionPerformed(evt);
	}//GEN-LAST:event_decimalDegreesActionPerformed

	private void menuToolsPatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuToolsPatternActionPerformed
		Object latHandle = ds.getHandle("Latitude");
		Object lonHandle = ds.getHandle("Longitude");

		Pos2D a = new Pos2D(0, 0);
		Pos2D b = new Pos2D(0, 0);
		
		if (ds.getSize() == 2) {
			a = new Pos2D(ds.getValue(latHandle, 0), ds.getValue(lonHandle, 0));
			b = new Pos2D(ds.getValue(latHandle, 1), ds.getValue(lonHandle, 1));
		}
	
		int h = 200;
		int touchdown = 0;
		int width = 600;
		int gpip = 1000;
		int hGpip = 100;
		int turn1 = 1000;
		int turn4 = 1500;
		int hTurn4 = 150;
		
		Pattern pattern = new Pattern(
				a, b, h, touchdown, width, gpip, hGpip, turn1, turn4, hTurn4, Pattern.LEFT);
				
		int res = JOptionPane.showConfirmDialog(
				this, pattern, 
				"Airfield trafic pattern", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		
		if (res == JOptionPane.OK_OPTION) {
			createDataSource();
			
			List<Pos3D> wpts = pattern.get();
			
			int index = 0;
			for (Pos3D wpt : wpts) {
				ds.addRow();
				ds.setValue(ds.getHandle("N"), index, index);
				ds.setValue(ds.getHandle("Latitude"), index, wpt.lat);
				ds.setValue(ds.getHandle("Longitude"), index, wpt.lon);
				ds.setValue(ds.getHandle("Altitude"), index, wpt.alt);
				++index;
			}
			
			recalcDataSource();
			updateTable();
		}
	}//GEN-LAST:event_menuToolsPatternActionPerformed

	private void menuFileAppendActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuFileAppendActionPerformed
		doOpenAppend(true);
	}//GEN-LAST:event_menuFileAppendActionPerformed

	private void doOpenAppend(boolean append) {
		final JFileChooser fc = new JFileChooser((lastDir != null) ? lastDir : getHomeDir());
		fc.setAcceptAllFileFilterUsed(false);
		FileNameExtensionFilter defaultFilter = new FileNameExtensionFilter("GCS flight plan (*.task)", "task");
		fc.addChoosableFileFilter(defaultFilter);
		fc.addChoosableFileFilter(new FileNameExtensionFilter("GoogleEarth KML (*.kml)", "kml"));
		fc.addChoosableFileFilter(new FileNameExtensionFilter("MissionPlanner (*.txt)", "txt"));
		fc.setFileFilter(defaultFilter);

		if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
			String desc = ((FileNameExtensionFilter)fc.getFileFilter()).getDescription();
			lastDir = fc.getSelectedFile().getParent();

			String path = fc.getSelectedFile().getPath();
			
			DataSourceReader dsReader;
			if (desc.startsWith("GCS"))
				dsReader = new TaskDataSourceReader();
			else if (desc.startsWith("Google"))
				dsReader = new KmlDataSourceReader();
			else if (desc.startsWith("Mission"))
				dsReader = new MissionPlannerDataSourceReader();
			else	
				return;
			
			doLoad(path, dsReader, append);
			recalcDataSource();
			updateTable();
		}
	}
	
	private void createDataSource() {
		ds = new DataSource();
		ds.addColumn("N", new SimpleFormatter(0, 0));
		ds.addColumn("Latitude", new DegMinSecFormatter("N", "S"));
		ds.addColumn("Longitude", new DegMinSecFormatter("E", "W"));
		ds.addColumn("Altitude", new SimpleFormatter(0, 0));		
	}
	
	private void doLoad(String path, DataSourceReader dsReader, boolean append) {
		filename = path;
		updateTitle(path);
		
		calc.getConfig().setFuelCalculated(false);
		
		if (ds == null || !append)
			createDataSource();
		
		Reader file = null;
		try {
			file = new FileReader(path);
			dsReader.process(file, ds);
        } catch (FileNotFoundException ex) {
			// do nothing
		} finally {
			try {
				if (file != null)
					file.close();
			} catch (IOException ex) {
				LOG.log(Level.SEVERE, null, ex);
			}
		}
	}
	
	private void doSave(String path, DataSourceWriter dsWriter) {
		BufferedWriter file = null;
		
		try {
			file = new BufferedWriter(new FileWriter(path));
			dsWriter.process(file, ds);
		} catch (IOException ex) {
			LOG.log(Level.SEVERE, null, ex);
		} finally {
			if (file != null) {
				try {
					file.close();
				} catch (IOException ex) {
					LOG.log(Level.SEVERE, null, ex);
				}
			}
		}
	}
	
	private void recalcDataSource() {
		calc.setDecimalDegrees(decimalDegrees.isSelected());
		calc.process(ds);
		updateUIFromConfig();
	}
	
	private void updateTable() {
		DefaultTableModel m = new DefaultTableModel() {
			@Override
			public boolean isCellEditable(int rowIndex, int mColIndex) {
				return false;
			}			
		};

		List<String> names = ds.getNames();
		m.setColumnIdentifiers(names.toArray());
		
		List<Object> handles = new ArrayList<Object>();
		for (String name : names)
			handles.add(ds.getHandle(name));
		
		NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
		nf.setMinimumFractionDigits(0);
		nf.setMaximumFractionDigits(10);
		
		for (int i = 0; i < ds.getSize(); ++i) {
			List<String> row = new ArrayList<String>();
			for (Object handle : handles) {
				row.add(ds.getValueAsString(handle, i));
			}
			m.addRow(row.toArray());
		}
		
		table.setModel(m);
	}
	
	private void updateUIFromConfig() {
		SimpleFormatter fmt = new SimpleFormatter(0, 1);
		TimeFormatter tfmt = new TimeFormatter(true);
		
		Config cfg = calc.getConfig();
		
		ias.setText(fmt.get(cfg.getAirSpeed()));
		windSpeed.setText(fmt.get(cfg.getWindSpeed()));
		windDir.setText(fmt.get(cfg.getWindDir()));
		fuelTotal.setText(fmt.get(cfg.getTotalFuel()));
		fuelRate.setText(fmt.get(cfg.getFuelFlow()));
		departure.setText(tfmt.get(cfg.getDepartureTime()));
	}
	
	private void updateConfigFromUI() {
		Config cfg = calc.getConfig();
		
		cfg.setAirSpeed(Double.parseDouble(ias.getText()));
		cfg.setWindSpeed(Double.parseDouble(windSpeed.getText()));
		cfg.setWindDir(Double.parseDouble(windDir.getText()));
		cfg.setTotalFuel(Double.parseDouble(fuelTotal.getText()));
		cfg.setFuelFlow(Double.parseDouble(fuelRate.getText()));
		
		String s = departure.getText();
		String[] ss = s.split(":");
		if (ss.length >= 3)
			cfg.setDepartureTime(Integer.parseInt(ss[ss.length - 1]) + Integer.parseInt(ss[ss.length - 2]) * 60 + Integer.parseInt(ss[ss.length - 3]) * 3600);
		else
			cfg.setDepartureTime(0);
	}
	

	/**
	 * Updates frame title.
	 * @param filename loaded log filename
	 */
	private void updateTitle(String filename) {
		setTitle(appTitle + (filename != null ? " [" +  filename + "]" : ""));
	}	
	
	/**
	 * Returns path to home directory
	 */
	private String getHomeDir() {
		return System.getProperty("user.dir");
	}
	

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton NowBtn;
    private javax.swing.JCheckBox decimalDegrees;
    private javax.swing.JFormattedTextField departure;
    private javax.swing.JTextField fuelRate;
    private javax.swing.JTextField fuelTotal;
    private javax.swing.JTextField ias;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JMenuBar menu;
    private javax.swing.JMenu menuFile;
    private javax.swing.JMenuItem menuFileAppend;
    private javax.swing.JMenuItem menuFileExit;
    private javax.swing.JMenuItem menuFileOpen;
    private javax.swing.JMenuItem menuFileSave;
    private javax.swing.JMenu menuTools;
    private javax.swing.JMenuItem menuToolsPattern;
    private javax.swing.JButton recalcButton;
    private javax.swing.JTable table;
    private javax.swing.JScrollPane tableScrollPane;
    private javax.swing.JTextField windDir;
    private javax.swing.JTextField windSpeed;
    // End of variables declaration//GEN-END:variables

	private String lastDir;
	private DataSource ds;
	private Calculator calc;
	private String filename;
	
	private static final String appTitle = "ZorNav v0.7";
}
